package util;

import constant.Common;
import constant.Regex;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

import java.security.SecureRandom;
import java.util.Collection;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字符串工具类
 *
 * @author zhanglinfeng
 * @date create in 2022/9/9 9:51
 */
public class StringUtil {
    private static final String RANDOM_CODE_STRING = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

    /**
     * 对象转字符串
     *
     * @param obj 待处理对象
     * @return String
     */
    public static String toString(Object obj) {
        return Optional.ofNullable(obj).orElse(Common.BLANK).toString();
    }

    /**
     * 判断对象是否为空
     *
     * @param obj 待判断对象
     * @return boolean
     */
    public static boolean isEmpty(Object obj) {
        if (obj instanceof Collection<?> col) {
            return col.isEmpty();
        }
        String str = toString(obj);
        return str == null || str.trim().isEmpty();
    }

    /**
     * 判断对象是否非空
     *
     * @param obj 待判断对象
     * @return boolean
     */
    public static boolean isNotEmpty(Object obj) {
        return !isEmpty(toString(obj));
    }

    /**
     * 首字母小写
     *
     * @param str 待处理字符串
     * @return String
     */
    public static String toLowerCaseFirst(String str) {
        if (isEmpty(str)) {
            return str;
        }
        char[] ch = str.toCharArray();
        if (ch[0] >= 65 && ch[0] <= 90) {
            ch[0] = (char) (ch[0] + 32);
        }
        return new String(ch);
    }

    /**
     * 首字母大写
     *
     * @param str 待处理字符串
     * @return String
     */
    public static String toUpperCaseFirst(String str) {
        if (isEmpty(str)) {
            return str;
        }
        char[] ch = str.toCharArray();
        if (ch[0] >= 97 && ch[0] <= 122) {
            ch[0] = (char) (ch[0] - 32);
        }
        return new String(ch);
    }

    /**
     * 正则获取首个匹配的字符串
     *
     * @param str   待处理字符串
     * @param regex 正则表达式
     * @return String
     */
    public static String getFirstMatcher(String str, String regex) {
        Matcher m = Pattern.compile(regex).matcher(str);
        return m.find() ? m.group(1) : Common.BLANK;
    }

    /**
     * 转驼峰格式
     *
     * @param str 待处理字符串
     * @return String
     */
    public static String toHumpStyle(String str) {
        StringBuilder result = new StringBuilder();
        char[] chars = str.toLowerCase().toCharArray();
        for (int i = 0; i < chars.length; i++) {
            String charStr = String.valueOf(chars[i]);
            if (chars[i] == 95) {
                i++;
                charStr = String.valueOf(chars[i]).toUpperCase();
            }
            result.append(charStr);
        }
        return result.toString();
    }

    /**
     * 获取汉字首字母
     *
     * @param chinese 汉字
     * @return String
     */
    public static String getChineseInitialLetter(String chinese) {
        if (isEmpty(chinese)) {
            return null;
        }
        char[] charArray = chinese.toCharArray();
        StringBuilder result = new StringBuilder();
        HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
        // 设置大小写格式
        defaultFormat.setCaseType(HanyuPinyinCaseType.UPPERCASE);
        // 设置声调格式：
        defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        for (char c : charArray) {
            // 匹配中文,非中文转换会转换成null
            if (Character.toString(c).matches(Regex.CHINESE)) {
                try {
                    Optional.ofNullable(PinyinHelper.toHanyuPinyinStringArray(c, defaultFormat)).ifPresent(t -> result.append(t[0].charAt(0)));
                } catch (BadHanyuPinyinOutputFormatCombination ignored) {
                }
            }
        }
        return result.toString();
    }

    /**
     * 指定位数的随机数字
     *
     * @param digit 位数
     * @return String
     */
    public static String randomNum(int digit) {
        SecureRandom random = new SecureRandom();
        StringBuilder returnValue = new StringBuilder();
        for (int i = 0; i < digit; i++) {
            returnValue.append(random.nextInt(10));
        }
        return returnValue.toString();
    }

    /**
     * 指定位数的随机字符串
     *
     * @param digit       位数
     * @param withNumbers true 带数字
     * @return int
     */
    public static String randomCode(int digit, boolean withNumbers) {
        int length = withNumbers ? RANDOM_CODE_STRING.length() : 26;
        SecureRandom random = new SecureRandom();
        StringBuilder returnValue = new StringBuilder();
        for (int i = 0; i < digit; i++) {
            int index = random.nextInt(length);
            returnValue.append(RANDOM_CODE_STRING.charAt(index));
        }
        return returnValue.toString();
    }
}
